"""
Description: dcdn 证书配置工具
Author: 嘎嘣脆的贝爷
Date: 2024-11-05 17:34:25
LastEditTime: 2024-11-05 17:34:38
LastEditors: 嘎嘣脆的贝爷
"""

from alibabacloud_dcdn20180115.client import Client as dcdn20180115Client
from alibabacloud_dcdn20180115 import models as dcdn_20180115_models
from alibabacloud_tea_openapi import models as open_api_models
from alibabacloud_tea_util import models as util_models
from tool import tool
from config import config
import asyncio


class AliDcdnAgent:
    """阿里云全站加速管理工具"""

    def __init__(self):
        # 要监测的域名列表
        self.domain_list = config.DOMAIN_LIST

        # 初始化客户端
        self.client = dcdn20180115Client(
            open_api_models.Config(
                access_key_id=config.ACCESS_KEY_ID,
                access_key_secret=config.ACCESS_KEY_SECRET,
                endpoint="dcdn.aliyuncs.com",
            )
        )

    async def __get_online_ssl_pub(self, domain: str) -> str:
        """获取域名当前配置的 ssl 公钥"""
        describe_dcdn_domain_certificate_info_request = (
            dcdn_20180115_models.DescribeDcdnDomainCertificateInfoRequest(
                domain_name=domain
            )
        )
        runtime = util_models.RuntimeOptions()
        try:
            # 复制代码运行请自行打印 API 的返回值
            rst = await self.client.describe_dcdn_domain_certificate_info_with_options_async(
                describe_dcdn_domain_certificate_info_request, runtime
            )
            return rst.body.cert_infos.cert_info[0].sslpub
        except Exception as error:
            print("获取域名当前配置 ssl 公钥出错:", error.message)

    async def __select_cert(self, domain: str, name: str):
        """选择证书"""
        batch_set_dcdn_domain_certificate_request = (
            dcdn_20180115_models.BatchSetDcdnDomainCertificateRequest(
                domain_name=domain, cert_name=name, cert_type="cas", sslprotocol="on"
            )
        )
        runtime = util_models.RuntimeOptions()
        try:
            await self.client.batch_set_dcdn_domain_certificate_with_options_async(
                batch_set_dcdn_domain_certificate_request, runtime
            )
        except Exception as error:
            print("dcnd 选择证书出错:", error.message)

    async def __check_cert(self, domains: list) -> list:
        """
        检查证书公钥与本地的是否一致
        parmas: domains - 域名列表
        return list[域名, 是否相等]
        """

        async def check(domain):
            local_pub = await tool.read(f"{domain}.pem")
            online_pub = await self.__get_online_ssl_pub(domain)
            return [domain, local_pub == online_pub]

        # 遍历比对
        return await asyncio.gather(*[check(d) for d in domains])

    def run(self, cert_info) -> None:
        """主任务"""
        # 检查域名的证书公钥是否一致
        print("检查域名的证书公钥与本地的是否一致...")
        rst = asyncio.run(self.__check_cert(self.domain_list))
        # 遍历结果，切换证书
        tasks = []
        for dlis in rst:
            if dlis[1]:
                continue
            tasks.append([dlis[0], cert_info[dlis[0]]["cert_name"]])

        async def select():
            await asyncio.gather(*[self.__select_cert(d[0], d[1]) for d in tasks])

        print(f"{tasks.__len__()} 个部署证书需要更换")
        print("更换中...")
        asyncio.run(select())
        print("任务执行完毕!")
